package ar.edu.itba.it.pdc;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;

import javax.imageio.ImageIO;
import javax.mail.internet.MimeUtility;

import ar.edu.itba.it.pdc.commons.Header;
import ar.edu.itba.it.pdc.commons.Mail;
import ar.edu.itba.it.pdc.commons.POP3Utils;

import com.google.common.io.LineReader;


public class Terminator {
	
	public static String CRLF = "\r\n";
	
	public static void main(String[] args) {
		Mail m = new Mail(System.in);
		filter(m, System.out);
	}

	public static void filter(Mail m, OutputStream out) {
		if (m.getContentType().contains("multipart")) {
			printHeaders(m, System.out);
			for (Mail p : m.getParts()) {
				filter(p, System.out);
			}
		} else {
			_filter(m, System.out);
		}
	}

	private static void printHeaders(Mail m, OutputStream stdout) {
		BufferedWriter out = new BufferedWriter(new OutputStreamWriter(stdout));

		try {
			for (Header h : m.getHeaders()) {
				out.write(POP3Utils.fold(0, h.getHeader()));
				out.write(CRLF);
			}
			out.write(CRLF);
			out.flush();
		} catch (Exception e) {

		}
	}
	
	public static void _filter(Mail m, OutputStream stdout) {
		BufferedWriter out = new BufferedWriter(new OutputStreamWriter(stdout));
		
		try{
			//Saltea headers
			printHeaders(m, stdout);
			
			String a;
			
			StringBuffer buf = new StringBuffer();
			
			if(m.getContentType().contains("image")) {
				
				LineReader lrb = m.getBody();
				while ((a = decode(m, lrb.readLine())) != null) {
					buf.append(a + CRLF);
				}
				
				byte[] imageBytes = buf.toString().getBytes();
				byte[] rotated = rotate(imageBytes, m.getContentType().split("/")[1]);
				
				String toWrite = encode(m, new String(rotated));
				
				out.write(toWrite);
				
			}else{
				LineReader lrb = m.getBody();
				while ((a = lrb.readLine()) != null) {
					out.write(a);
					out.write(CRLF);
				}
				out.write(CRLF);
			}
			out.flush();
		}catch(Exception e) {
		}
		
	}
	
	public static byte[] rotate(byte[] imageBytes, String f) {
		try{
			BufferedImage img = ImageIO.read(new ByteArrayInputStream(imageBytes));
			int w = img.getWidth();
			int h = img.getHeight();
			
			BufferedImage aux = new BufferedImage(w, h, img.getType());
			
			Graphics2D g = aux.createGraphics();
			g.rotate(Math.toRadians(180), w/2, h/2);
			g.drawImage(img, null, 0, 0);
			
			ByteArrayOutputStream resp = new ByteArrayOutputStream(img.getHeight()*img.getWidth());
			ImageIO.write(aux, f, resp);
			return resp.toByteArray();
		}catch(Exception e) {
			return imageBytes;
		}
	}
	
	private static String decode(Mail m, String s) {
		if (s == null) {
			return null;
		} else if (s.isEmpty()) {
			return "";
		} else {
			try {
				BufferedReader resp = new BufferedReader(new InputStreamReader(
						MimeUtility.decode(
								new ByteArrayInputStream(s.getBytes()), m
										.getContentTransferEncoding()
										.getValue())));
				String r = resp.readLine();
				return r;
			} catch (Exception e) {
			}
			return s;
		}
	}

	private static String encode(Mail m, String s) {
		if (s == null) {
			return null;
		} else if (s.isEmpty()) {
			return "";
		} else {
			try {
				ByteArrayOutputStream out = new ByteArrayOutputStream();
				OutputStream encoder = MimeUtility.encode(out, m.getContentTransferEncoding().getValue());

				encoder.write(s.getBytes(), 0, s.length());
				encoder.flush();

				return new String(out.toByteArray());

			} catch (Exception e) {
			}
		}
		return s;
	}
}
